home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / misc / dptool / dpani.asm < prev    next >
Encoding:
Assembly Source File  |  1994-11-02  |  28.7 KB  |  1,085 lines

  1. ;   []--------------------------------------------------[]
  2. ;    |                     dpani.asm                      |
  3. ;    |                                                    |
  4. ;   | Deluxe Paint II Enhanced (v2.3) Animation TSR.     |
  5. ;    |                                                    |
  6. ;   | Assemble with TASM 3.1 or greater.                 |
  7. ;   |                                                    |
  8. ;   |           Copyright Carl Chimes 1993               |
  9. ;    []--------------------------------------------------[]
  10.  
  11. IDEAL
  12. MODEL TINY,C
  13.  
  14. P8086
  15. SMART
  16. LOCALS
  17.  
  18. ;----------------------------------------------------------
  19. ; IIF (Instruction IF) MACRO
  20. ;
  21. ; pre:    cond = condition to execute instruc
  22. ;    instruc = instruction to execute
  23. ; post:    instruc executed if cond true, code continued
  24. ;----------------------------------------------------------
  25.  
  26. MACRO IIF    cond,instruc
  27. LOCAL cont1
  28.  
  29.     IFIDNI <cond>, <e>
  30.         jne short cont1       ;; e -- ne
  31.     ELSEIFIDNI <cond>, <z>
  32.         jnz short cont1       ;; z -- nz
  33.     ELSEIFIDNI <cond>, <ne>
  34.         je short cont1        ;; ne -- e
  35.     ELSEIFIDNI <cond>, <nz>
  36.         jz short cont1        ;; nz -- z
  37.     ELSEIFIDNI <cond>, <c>
  38.         jnc short cont1       ;; c -- nc
  39.     ELSEIFIDNI <cond>, <nc>
  40.         jc short cont1        ;; nc -- c
  41.     ELSEIFIDNI <cond>, <a>
  42.         jbe short cont1       ;; a -- be
  43.     ELSEIFIDNI <cond>, <b>
  44.         jae short cont1       ;; b -- ae
  45.     ELSEIFIDNI <cond>, <ae>
  46.         jb short cont1        ;; ae -- b
  47.     ELSEIFIDNI <cond>, <be>
  48.         ja short cont1        ;; be -- a
  49.     ELSEIFIDNI <cond>, <g>
  50.         jle short cont1       ;; g -- le
  51.     ELSEIFIDNI <cond>, <l>
  52.         jge short cont1       ;; l - ge
  53.     ELSEIFIDNI <cond>, <ge>
  54.         jl short cont1        ;; ge -- l
  55.     ELSEIFIDNI <cond>, <le>
  56.         jg short cont1        ;; le -- g
  57.     ELSEIFIDNI <cond>, <o>
  58.         jno short cont1       ;; o -- no
  59.     ELSEIFIDNI <cond>, <no>
  60.         jo short cont1        ;; no -- o
  61.     ELSEIFIDNI <cond>, <p>
  62.         jnp short cont1       ;; p -- np
  63.     ELSEIFIDNI <cond>, <pe>
  64.         jnp short cont1       ;; pe -- np
  65.     ELSEIFIDNI <cond>, <po>
  66.         jp short cont1        ;; pe -- np
  67.     ELSEIFIDNI <cond>, <np>
  68.         jp short cont1        ;; np -- p
  69.     ELSEIFIDNI <cond>, <s>
  70.         jns short cont1       ;; s -- ns
  71.     ELSEIFIDNI <cond>, <ns>
  72.         js short cont1        ;; ns -- s
  73.     ELSE
  74.         ERR <Error in IIF>
  75.     ENDIF
  76.  
  77.     instruc                ;; execute instruc
  78. cont1:
  79. ENDM
  80.  
  81.  
  82.  
  83. ;* initialised data *****************************************
  84. DATASEG
  85.  
  86. ;* uninitialised data ***************************************
  87. UDATASEG
  88.  
  89. ;* constants ************************************************
  90.  
  91. MultiplexCode    equ 0CCh    ; the multiplex code
  92. MPRequestShutdown equ 01h    ; function to request shutdown from Multiplex Int
  93.                 ; it restores all sw interrupts and returns
  94.                 ; paragraph address of TSR in ax
  95. BaseDPCodeSegConst   equ 5AC6h
  96.  
  97.  
  98. ENUM AnimationTypes {
  99.     AniTypeCycle=0      ; cycle animation
  100.     AniTypeRamp         ; ramp animation
  101.     AniTypeCount        ; nr of animation types
  102. }
  103.  
  104.  
  105. ; key scan codes
  106. Key_Alt_GREYENTER = 0a600h
  107. Key_GREYENTER     = 0e00dh
  108. Key_F11         = 08500h
  109. Key_F12         = 08600h
  110. Key_Alt_W       = 01100h
  111. Key_Alt_H       = 02300h
  112. Key_Alt_M       = 03200h
  113. Key_ESC         = 0011bh
  114. Key_Alt_1       = 07800h
  115. Key_Alt_2       = 07900h
  116. Key_Alt_GREYLEFT = 09b00h
  117. Key_Alt_GREYRIGHT= 09d00h
  118. Key_Alt_GREYUP   = 09800h
  119. Key_Alt_GREYDOWN = 0a000h
  120.  
  121. ;
  122. ; Pre: dpseg!=ax and dpofs!=ax
  123. ;
  124. MACRO CallFar dpseg,dpofs
  125.     push ax
  126.     mov ax,[cs:BaseDPCodeSeg]
  127.     add ax,dpseg
  128.     sub ax,BaseDPCodeSegConst
  129.     mov [WORD HIGH cs:tempAddr],ax
  130.     mov ax,dpofs
  131.     mov [WORD LOW cs:tempAddr],ax
  132.     pop ax
  133.     call [DWORD cs:tempAddr]
  134. ENDM
  135.  
  136. ;* code *****************************************************
  137.  
  138. CODESEG
  139.  
  140.     STARTUPCODE
  141.     jmp InitAndTerminate
  142.  
  143.  
  144. ;* code data ************************************************
  145.  
  146. startupKbVec        dd ?        ; startup keyboard int 16h
  147. startupMultiplexVec dd ?        ; startup multiplex int 2fh
  148. startupTickerVec    dd ?        ; startup ticker int 08h
  149. runtimeDosVec        dd ?    ; runtime dos vector 21h
  150. dpRunning   dw 0                ; whether dp is running
  151. BaseDPCodeSeg   dw 0                ; the actual value of the base segment
  152. dsDPSeg     dw 0                ; data segment of dp
  153. tempAddr    dd ?                ; temporary address
  154.  
  155. ; animation variables
  156. aniOn           dw 0            ; whether animation is on
  157. aniPixmapWidth  dw 16           ; width of each pixmap in animation
  158. aniPixmapHeight dw 16           ; height of each pixmap in animation
  159. aniMultiWidth   dw 1            ; nr of pixmaps width in multi-block frame
  160. aniMultiHeight  dw 1            ; nr of pixmaps height in multi-block frame
  161. aniMultiOn      dw 0            ; whether in multi-mode
  162. aniFirst        dw 0            ; first pixmap in sequence
  163. aniLast         dw 0            ; last pixmap in sequence
  164. aniQty          dw 1            ; nr of pixmaps in sequence
  165. aniCur          dw 0            ; current pixmap in sequence
  166. aniDirn         dw 0            ; current animation direction (for ramp)
  167. aniType         dw AniTypeCycle ; type of animation
  168. aniSpeedDelay   dw 2            ; speed delay
  169. aniSpeedCount   dw 0            ; speed count
  170. aniViewX        dw 0            ; x coord at which to view current frame
  171. aniViewY        dw -1           ; y coord at which to view current frame (-1 means at bottom of screen)
  172.  
  173.  
  174. ;------------------------------------------------------------
  175. ; dpCodeCheck is a byte pattern against which to compare
  176. ; calling code. If a match occurs assume calling code is
  177. ; Deluxe Paint II Enhanced v2.3.
  178. ; Note that other versions of Deluxe Paint are likely to
  179. ; have this code too so dpAni is likely to detect a bad
  180. ; version and think it's okay.
  181. ;------------------------------------------------------------
  182. dpCodeCheck:
  183.     jz    short @@5AC6_067B
  184.     mov   ax,0FFFFh
  185.     retf
  186. @@5AC6_067B:
  187.     xor ax,ax
  188.     retf
  189.     mov   ah,0
  190.     int   16h
  191.     or    al,al
  192.     jz    short @@5AC6_0688
  193.     xor   ah,ah
  194. @@5AC6_0688:
  195.     retf
  196.  
  197. dpCodeCheckLength = ((OFFSET $) - (OFFSET dpCodeCheck))
  198.  
  199.  
  200. ;* real code ************************************************
  201.  
  202. ;------------------------------------------------------------
  203. ; myDosInt
  204. ;
  205. ; my dos int - used to trap exit in DP
  206. ;
  207. ;
  208. ;------------------------------------------------------------
  209. PROC myDosInt NEAR
  210.  
  211.     ASSUME ds:NOTHING, ss:NOTHING
  212.  
  213.     cmp ah,4Ch
  214.     je @@detach
  215.     cmp ah,00h
  216.     je @@detach
  217.  
  218.     pushf
  219.     call [DWORD cs:runtimeDosVec]    ; simulate call to true dos vector
  220.     retf 2                            ; preserve flags
  221.  
  222. @@detach:
  223.     mov [dpRunning],0            ; dp no longer running
  224.     mov [aniOn],0               ; no more animation
  225.  
  226.     push ax
  227.     push bx
  228.     push es
  229.     sub bx,bx
  230.     mov es,bx
  231.     mov bx,21h*4
  232.     mov ax,[WORD cs:runtimeDosVec]
  233.     mov [WORD es:bx],ax
  234.     mov ax,[WORD HIGH cs:runtimeDosVec]
  235.     mov [WORD es:bx+2],ax    ; restore runtime dos vector
  236.     pop es
  237.     pop bx
  238.     pop ax
  239.  
  240.     pushf
  241.     call [DWORD cs:runtimeDosVec]    ; now do function
  242.     retf 2                ; preserve flags
  243.  
  244. ENDP myDosInt
  245.  
  246.  
  247. ;------------------------------------------------------------
  248. ; myKbInt
  249. ;
  250. ; My keyboard interrupt, patching int 16h
  251. ;
  252. ;
  253. ;------------------------------------------------------------
  254. PROC myKbInt NEAR
  255.  
  256.     ASSUME ds:NOTHING, ss:NOTHING
  257.  
  258.     push ax bx cx dx es
  259.     call doDelayedAniStep
  260.     pop es dx cx bx ax
  261.  
  262.     cmp ah,1
  263.     je @@readchar
  264.  
  265.     pushf
  266.     call [DWORD cs:startupKbVec]    ; jmp to old int
  267.     retf 2                          ; must preserve flags
  268.  
  269. @@readchar:
  270.     mov ah,11h
  271.     pushf
  272.     call [DWORD cs:startupKbVec]    ; do an extended read
  273.     IIF z,<jmp @@returnread>        ; no chars, return
  274.  
  275.     ; char is available - dispatch to my routines if is one of mine
  276.  
  277.     cmp ax,Key_F12
  278.     IIF e,<jmp @@AttachToDP>    ; attach to DP
  279.  
  280.     cmp [dpRunning],0
  281.     IIF e,<jmp @@returnread>    ; deluxe paint not running - do no functions
  282.  
  283.     cmp ax,Key_GREYENTER
  284.     IIF e,<jmp @@SetFirstPixmap> ; set first endpoint of animation
  285.     cmp ax,Key_Alt_GREYENTER
  286.     IIF e,<jmp @@SetLastPixmap> ; set last endpoint of animation
  287.     cmp ax,Key_F11
  288.     IIF e,<jmp @@PauseContinue> ; pause/continue animation
  289.     cmp ax,Key_Alt_GREYRIGHT
  290.     IIF e,<jmp @@SingleStepFwd> ; single step of animation forwards
  291.     cmp ax,Key_Alt_GREYLEFT
  292.     IIF e,<jmp @@SingleStepRev> ; single step of animation reverse
  293.     cmp ax,Key_Alt_GREYUP
  294.     IIF e,<jmp @@SpeedIncrease> ; increase speed
  295.     cmp ax,Key_Alt_GREYDOWN
  296.     IIF e,<jmp @@SpeedDecrease> ; decrease speed
  297.     cmp ax,Key_Alt_W
  298.     IIF e,<jmp @@SetWidth>      ; set width of pixmap
  299.     cmp ax,Key_Alt_H
  300.     IIF e,<jmp @@SetHeight>     ; set height of pixmap
  301.     cmp ax,Key_Alt_1
  302.     IIF e,<jmp @@SetAniType1>   ; set animation type 1
  303.     cmp ax,Key_Alt_2
  304.     IIF e,<jmp @@SetAniType2>   ; set animation type 2
  305.     cmp ax,Key_Alt_M
  306.     IIF e,<jmp @@ToggleMulti>   ; toggle multiblock sprites
  307.     jmp @@returnread            ; no function, behave normally
  308.  
  309. @@SetFirstPixmap:
  310.     mov ah,10h
  311.     pushf
  312.     call [DWORD cs:startupKbVec]    ; remove function  invoking key from buffer
  313.     mov ah,10h
  314.     pushf
  315.     call [DWORD cs:startupKbVec]    ; get pixmap number
  316.     dec ax                          ; adjust since lowest enterable nr is 1
  317.     push ax
  318.     call clampPixmapNrToScreen      ; put in legal range
  319.     add sp,2
  320.     mov [aniFirst],ax           ; set aniFirst
  321.     mov [aniCur],ax             ; set current to new first
  322.     add ax,[aniQty]
  323.     dec ax                      ; new last
  324.     push ax
  325.     call clampPixmapNrToScreen      ; put in legal range
  326.     add sp,2
  327.     mov [aniLast],ax            ; store new last
  328.     jmp @@readchar              ; check next in buffer
  329.  
  330. @@SetLastPixmap:
  331.     mov ah,10h
  332.     pushf
  333.     call [DWORD cs:startupKbVec]    ; remove function  invoking key from buffer
  334.     mov ah,10h
  335.     pushf
  336.     call [DWORD cs:startupKbVec]    ; get nr of pixmaps in sequence
  337.     mov [aniQty],ax
  338.     add ax,[aniFirst]
  339.     dec ax                          ; convert qty to last pixmap
  340.     push ax
  341.     call clampPixmapNrToScreen      ; put in legal range
  342.     add sp,2
  343.     mov [aniLast],ax            ; set aniLast
  344.     mov ax,[aniFirst]
  345.     mov [aniCur],ax             ; new cur = first
  346.     jmp @@readchar              ; check next in buffer
  347.  
  348. @@PauseContinue:
  349.     xor [aniOn],1               ; toggle whether on (not-paused)
  350.     jmp @@removeandtrynext      ; check next in buffer
  351.  
  352. @@SingleStepRev:
  353.     push ax bx cx dx es
  354.     call aniStepOnceRev
  355.     pop es dx cx bx ax
  356.     jmp @@removeandtrynext      ; check next in buffer
  357.  
  358. @@SingleStepFwd:
  359.     push ax bx cx dx es
  360.     call aniStepOnceFwd
  361.     pop es dx cx bx ax
  362.     jmp @@removeandtrynext      ; check next in buffer
  363.  
  364. @@SpeedIncrease:                ; speed increase
  365.     cmp [aniSpeedDelay],0
  366.     je @@speedinccont           ; if aniDelay>0
  367.     dec [aniSpeedDelay]         ;  aniDelay--
  368. @@speedinccont:
  369.     jmp @@removeandtrynext      ; check next in buffer
  370.  
  371. @@SpeedDecrease:
  372.     cmp [aniSpeedDelay],0FFFFh
  373.     je @@speeddeccont           ; if aniDelay<0FFFFh
  374.     inc [aniSpeedDelay]         ;  aniDelay++
  375. @@speeddeccont:
  376.     jmp @@removeandtrynext      ; check next in buffer
  377.  
  378. @@SetWidth:
  379.     mov ah,10h
  380.     pushf
  381.     call [DWORD cs:startupKbVec]    ; remove function  invoking key from buffer
  382.     mov ah,10h
  383.     pushf
  384.     call [DWORD cs:startupKbVec]    ; get width in pixels
  385.     push ds
  386.     mov ds,[cs:dsDPSeg]
  387.     cmp ax,[WORD ds:98h]            ; width of screen
  388.     jle @@setwidcont1               ; if width>screenwidth
  389.     mov ax,[WORD ds:98h]            ;  width=screenwidth
  390. @@setwidcont1:
  391.     pop ds
  392.     mov [aniPixmapWidth],ax         ; store width
  393.  
  394.     mov ax,[aniFirst]
  395.     call clampPixmapNrToScreen
  396.     mov [aniFirst],ax               ; make sure first pixmap nr on screen
  397.     mov ax,[aniLast]
  398.     call clampPixmapNrToScreen
  399.     mov [aniLast],ax                ; make sure last pixmap nr on screen
  400.     mov ax,[aniCur]
  401.     call clampPixmapNrToScreen
  402.     mov [aniCur],ax                 ; make sure cur pixmap nr on screen
  403.     jmp @@readchar                  ; try next in buffer
  404.  
  405. @@SetHeight:
  406.     mov ah,10h
  407.     pushf
  408.     call [DWORD cs:startupKbVec]    ; remove function  invoking key from buffer
  409.     mov ah,10h
  410.     pushf
  411.     call [DWORD cs:startupKbVec]    ; get height in pixels
  412.     push ds
  413.     mov ds,[cs:dsDPSeg]
  414.     cmp ax,[WORD ds:9Ah]            ; height of screen
  415.     jle @@sethgtcont1               ; if height>screenheight
  416.     mov ax,[WORD ds:9Ah]            ;  height=screenheight
  417. @@sethgtcont1:
  418.     pop ds
  419.     mov [aniPixmapHeight],ax        ; store height
  420.  
  421.     mov ax,[aniFirst]
  422.     call clampPixmapNrToScreen
  423.     mov [aniFirst],ax               ; make sure first pixmap nr on screen
  424.     mov ax,[aniLast]
  425.     call clampPixmapNrToScreen
  426.     mov [aniLast],ax                ; make sure last pixmap nr on screen
  427.     mov ax,[aniCur]
  428.     call clampPixmapNrToScreen
  429.     mov [aniCur],ax                 ; make sure cur pixmap nr on screen
  430.     jmp @@readchar                  ; try next in buffer
  431.  
  432. @@SetAniType1:
  433.     mov [aniType],AniTypeCycle
  434.     jmp @@removeandtrynext
  435.  
  436. @@SetAniType2:
  437.     mov [aniType],AniTypeRamp
  438.     jmp @@removeandtrynext
  439.  
  440. @@ToggleMulti:                      ; toggle multiblock sprite
  441.     xor [aniMultiOn],1
  442.     jz @@multioff
  443.     ; turn multi on
  444.     mov [aniMultiWidth],2   ; turn multi on
  445.     mov [aniMultiHeight],2
  446.     jmp @@multicont
  447. @@multioff:                 ; turn multi off
  448.     mov [aniMultiWidth],1
  449.     mov [aniMultiHeight],1
  450. @@multicont:
  451.     jmp @@removeandtrynext
  452.  
  453. @@AttachToDP:                   ; attach to DP
  454.  
  455.     ; check if already attached
  456.     cmp [cs:dpRunning],0
  457.     IIF ne,<jmp @@removeandtrynext> ; already (attached), check next in buffer
  458.  
  459.     ; check if DP is really running
  460.     push bp
  461.     mov bp,sp
  462.     push cx
  463.     push si
  464.     push di
  465.     push es
  466.     push ds
  467.     les di,[bp+2]                ; esdi= calling code return addr
  468.     push cs
  469.     pop ds
  470.     mov si,OFFSET dpCodeCheck    ; dssi= code check start
  471.     mov cx,dpCodeCheckLength
  472.     repe cmpsb
  473.     jne @@attachdetachend       ; not a match - do nothing
  474.  
  475.     ; was a match - attach to DP
  476.     mov [cs:dpRunning],1
  477.  
  478.     ; save segments
  479.     mov [cs:BaseDPCodeSeg],es   ; save base segment
  480.     pop ds
  481.     push ds                        ; ds= calling data segment
  482.     mov [cs:dsDPSeg],ds            ; store in dsDPSeg
  483.  
  484.     ; hook into Dos Int to catch when DP exits
  485.     push ax
  486.     push bx
  487.     push es
  488.     sub bx,bx
  489.     mov es,bx
  490.     mov bx,21h*4
  491.     ; get runtime dos vector
  492.     mov ax,[WORD es:bx]
  493.     mov [WORD cs:runtimeDosVec],ax
  494.     mov ax,[WORD es:bx+2]
  495.     mov [WORD HIGH cs:runtimeDosVec],ax    ; orig vector gotten
  496.     ; install my dos vector
  497.     mov ax,OFFSET myDosInt
  498.     mov [WORD es:bx],ax
  499.     mov [WORD es:bx+2],cs    ; my dos vector installed
  500.     pop es
  501.     pop bx
  502.     pop ax
  503.  
  504.     ; test code - signal readiness of dpAni
  505.     mov di,0a000h
  506.     mov es,di
  507.     mov di,0
  508.     add [WORD es:di],0101h
  509.  
  510. @@attachdetachend:
  511.     pop ds
  512.     pop es
  513.     pop di
  514.     pop si
  515.     pop cx
  516.     pop bp                        ; restore regs used in attach
  517.     jmp short @@removeandtrynext
  518.  
  519. @@removeandtrynext:
  520.     mov ah,10h                      ; wait key function
  521.     pushf
  522.     call [DWORD cs:startupKbVec]    ; remove key from buffer
  523.     jmp @@readchar
  524.  
  525. @@returnread:                   ; now do a limited read
  526.     mov ah,1
  527.     pushf
  528.     call [DWORD cs:startupKbVec]    ; call old interrupt
  529.     retf 2                          ; must preserve flags
  530. ENDP myKbInt
  531.  
  532.  
  533. ;------------------------------------------------------------
  534. ; clampPixmapNrToScreen
  535. ;
  536. ; clamp pixmap nr (arg0) to valid screen range
  537. ;
  538. ;
  539. ;------------------------------------------------------------
  540. PROC clampPixmapNrToScreen NEAR
  541. ARG pixmapnr
  542. USES ax,bx,dx,ds
  543.  
  544.     ASSUME ds:NOTHING,ss:NOTHING
  545.     mov ds,[dsDPSeg]        ; set ds to deluxe paints data seg
  546.  
  547.     mov ax,[ds:98h]
  548.     cwd                     ; dxax= width of screen
  549.     div [aniPixmapWidth]
  550.     mov bx,ax               ; bx= nr pixmaps across screen
  551.  
  552.     mov ax,[ds:9Ah]
  553.     cwd                     ; dxax= height of screen
  554.     div [aniPixmapHeight]   ; ax = nr pixmaps down screen
  555.  
  556.     mul bx
  557.     mov bx,ax               ; bx = max legal pixmap+1
  558.  
  559.     mov ax,[pixmapnr]
  560.     cmp ax,0
  561.     jge @@cont1             ; if (ax<0)
  562.     sub ax,ax               ;  ax=0
  563.     jmp @@return
  564. @@cont1:
  565.     cmp ax,bx
  566.     jl @@return             ; if (ax>bx)
  567.     mov ax,bx
  568.     dec ax                  ;  ax = bx-1
  569. @@return:
  570.     ret
  571. ENDP clampPixmapNrToScreen
  572.  
  573.  
  574. ;------------------------------------------------------------
  575. ; showFrame
  576. ;
  577. ; Shows the current animation frame at (aniViewX,aniViewY)
  578. ; The current frame is aniCur, with dimension (aniPixmapWidth,aniPixmapHeight)
  579. ;
  580. ;------------------------------------------------------------
  581. PROC showFrame NEAR
  582. LOCAL ViewX,ViewY,ViewLeftX,PageLeftX,PageTopY
  583. USES ds
  584.  
  585.     ASSUME ds:NOTHING,ss:NOTHING
  586.  
  587.     mov ds,[dsDPSeg]        ; set ds to deluxe paints data seg
  588.  
  589.     CallFar 045D8h,0AD8h    ; hide mouse
  590.  
  591.  
  592.     ; find actual view x (may be -ve aniViewX => dist from right)
  593.     mov ax,[aniViewX]
  594.     cmp ax,0
  595.     jge @@contx
  596.     inc ax
  597.     add ax,[WORD ds:98h]    ; width of screen
  598.     mov bx,ax
  599.     mov ax,[aniPixmapWidth]
  600.     mul [aniMultiWidth]
  601.     neg ax
  602.     add ax,bx               ; ax= aniViewX+1 + scrwidth - aniPixmapWidth*aniMultiWidth
  603. @@contx:
  604.     mov [ViewLeftX],ax      ; store actual view X
  605.  
  606.     ; find actual view y (may be -ve aniViewY => dist from bottom)
  607.     mov ax,[aniViewY]
  608.     cmp ax,0
  609.     jge @@conty
  610.     inc ax
  611.     add ax,[WORD ds:9Ah]    ; height of screen
  612.     mov bx,ax
  613.     mov ax,[aniPixmapHeight]
  614.     mul [aniMultiHeight]
  615.     neg ax
  616.     add ax,bx               ; ax = aniViewY+1 + scrheight - aniPixmapHeight*aniMultiHeight
  617. @@conty:
  618.     mov [ViewY],ax          ; store actual view X
  619.  
  620.  
  621.     ; find coords of aniCur on page
  622.     mov ax,[ds:98h]
  623.     cwd                     ; dxax= width of screen
  624.     div [aniPixmapWidth]
  625.     mov bx,ax               ; bx= nr pixmaps across screen
  626.     mov ax,[aniCur]
  627.     div bx                  ; ax=y block coord, dx=x block coord
  628.     mov bx,dx
  629.     mul [aniPixmapHeight]
  630.     mov [PageTopY],ax       ; [PageTopY]= pixheight*(cur/(scrwidth/pixwidth))
  631.     mov ax,bx
  632.     mul [aniPixmapWidth]
  633.     mov [PageLeftX],ax      ; [PageLeftX]= pixwidth*(cur%(scrwidth/pixwidth))
  634.  
  635.     mov cx,[aniMultiHeight]
  636. @@loopy:
  637.     push cx
  638.  
  639.     mov ax,[ViewLeftX]
  640.     mov [ViewX],ax          ; ViewX= ViewLeftX
  641.     mov cx,[aniMultiWidth]
  642. @@loopx:
  643.     push cx
  644.  
  645.     sub ax,ax
  646.     push ax                 ;+16=0
  647.     push [aniPixmapHeight]  ;+14=   hgt of region on screen
  648.     push [aniPixmapWidth]   ;+12=   wid of region on screen
  649.     push [ViewY]            ;+10=0  y top of region on screen
  650.     push [ViewX]            ;+0E=0  x left of region on screen
  651.     mov    ax,0B6C8h
  652.     push ax
  653.     push [PageTopY]         ;+0A=0  start y coord on page
  654.     push [PageLeftX]        ;+8=0   start x coord on page
  655.     mov    ax,52h
  656.     push ax                 ;+6=52h ptr
  657.     CallFar 03cadh,00fah    ; call DP's draw pixmap routine
  658.     add sp,12h
  659.  
  660.     mov ax,[aniPixmapWidth]
  661.     add [ViewX],ax          ; ViewX += aniPixmapWidth
  662.  
  663.     pop cx
  664.     loop @@loopx            ; loop for all aniMultiWidth
  665.  
  666.     mov ax,[aniPixmapHeight]
  667.     add [ViewY],ax          ; ViewY += aniPixmapHeight
  668.  
  669.     pop cx
  670.     loop @@loopy            ; loop for all aniMultiHeight
  671.  
  672.     CallFar 045D8h,0A94h    ; show mouse
  673.  
  674.     ret
  675. ENDP showFrame
  676.  
  677.  
  678. ;------------------------------------------------------------
  679. ; aniStepOnceFwd
  680. ;
  681. ; do one animation step forwards regardless of aniOn
  682. ;
  683. ;
  684. ;------------------------------------------------------------
  685. PROC aniStepOnceFwd
  686.     ASSUME ds:NOTHING,ss:NOTHING
  687.  
  688.     mov ax,[aniFirst]
  689.     cmp ax,[aniLast]
  690.     jge @@showandreturn         ; if (first>=last) return
  691.  
  692.     mov bx,[aniType]
  693.     cmp bx,AniTypeCycle
  694.     je @@cycle                  ; dispatch to cycle
  695.     cmp bx,AniTypeRamp
  696.     je @@ramp                   ; dispatch to ramp
  697.     jmp @@return                ; invalid anitype return
  698.  
  699. @@cycle:                        ; cycle {
  700.     inc [aniCur]                ;  cur++;
  701.     mov ax,[aniCur]
  702.     cmp ax,[aniLast]
  703.     jle @@cycledone             ;  if cur>last
  704.     mov ax,[aniFirst]           ;  {
  705.     mov [aniCur],ax             ;   cur= first;
  706. @@cycledone:                    ;  }
  707.     jmp @@showandreturn                ; return
  708.  
  709. @@ramp:
  710.     cmp [aniDirn],0
  711.     jne @@rampgoingdown
  712.  
  713. @@rampgoingup:
  714.     inc [aniCur]                ; aniCur++
  715.     mov ax,[aniLast]
  716.     cmp [aniCur],ax
  717.     jle @@rampupcont          ; if (cur>last)
  718.     dec ax
  719.     mov [aniCur],ax             ;   cur=last-1
  720.     mov [aniDirn],1             ;   dirn= down
  721. @@rampupcont:
  722.     jmp @@showandreturn
  723.  
  724. @@rampgoingdown:
  725.     dec [aniCur]                ; aniCur--
  726.     mov ax,[aniFirst]
  727.     cmp [aniCur],ax
  728.     jge @@rampdowncont            ; if (cur<first)
  729.     inc ax
  730.     mov [aniCur],ax             ;  cur= first+1
  731.     mov [aniDirn],0             ;  dirn= up
  732. @@rampdowncont:
  733.     jmp @@showandreturn
  734.  
  735. @@showandreturn:
  736.     call showFrame              ;  show the current frame
  737. @@return:
  738.     ret
  739. ENDP aniStepOnceFwd
  740.  
  741.  
  742. ;------------------------------------------------------------
  743. ; aniStepOnceRev
  744. ;
  745. ; do one animation step in reverse regardless of aniOn
  746. ;
  747. ;
  748. ;------------------------------------------------------------
  749. PROC aniStepOnceRev
  750.     ASSUME ds:NOTHING,ss:NOTHING
  751.  
  752.     mov ax,[aniFirst]
  753.     cmp ax,[aniLast]
  754.     jge @@showandreturn         ; if (first>=last) return
  755.  
  756.     mov bx,[aniType]
  757.     cmp bx,AniTypeCycle
  758.     je @@cycle                  ; dispatch to cycle
  759.     cmp bx,AniTypeRamp
  760.     je @@ramp                   ; dispatch to ramp
  761.     jmp @@return                ; invalid anitype return
  762.  
  763. @@cycle:                        ; cycle {
  764.     dec [aniCur]                ;  cur--;
  765.     mov ax,[aniCur]
  766.     cmp ax,[aniFirst]
  767.     jge @@cycledone              ;  if cur<first
  768.     mov ax,[aniLast]            ;  {
  769.     mov [aniCur],ax             ;   cur= last;
  770. @@cycledone:                    ;  }
  771.     jmp @@showandreturn                ; return
  772.  
  773. @@ramp:
  774.     cmp [aniDirn],1             ; if ! going down
  775.     jne @@rampgoingdown         ; do reverse of normal
  776.  
  777. @@rampgoingup:
  778.     inc [aniCur]                ; aniCur++
  779.     mov ax,[aniLast]
  780.     cmp [aniCur],ax
  781.     jle @@rampupcont          ; if (cur>last)
  782.     dec ax
  783.     mov [aniCur],ax             ;   cur=last-1
  784.     mov [aniDirn],0             ;   dirn= up
  785. @@rampupcont:
  786.     jmp @@showandreturn
  787.  
  788. @@rampgoingdown:
  789.     dec [aniCur]                ; aniCur--
  790.     mov ax,[aniFirst]
  791.     cmp [aniCur],ax
  792.     jge @@rampdowncont          ; if (cur<first)
  793.     inc ax
  794.     mov [aniCur],ax             ;  cur= first+1
  795.     mov [aniDirn],1             ;  dirn= down
  796. @@rampdowncont:
  797.     jmp @@showandreturn
  798. @@showandreturn:
  799.     call showFrame              ;  show the current frame
  800. @@return:
  801.     ret
  802. ENDP aniStepOnceRev
  803.  
  804.  
  805. ;------------------------------------------------------------
  806. ; doDelayedAniStep
  807. ;
  808. ; Does an animation step every aniDelay ticker ticks
  809. ;
  810. ;
  811. ;------------------------------------------------------------
  812. PROC doDelayedAniStep NEAR
  813.  
  814.     ASSUME ds:NOTHING,ss:NOTHING
  815.  
  816.     cmp [aniOn],0
  817.     je @@return                 ; animation not on, return
  818.  
  819.     cmp [aniSpeedCount],0       ; aniSpeedCount is decremented on int8
  820.     jg @@return                 ; if count>0 return
  821.     mov ax,[aniSpeedDelay]
  822.     mov [aniSpeedCount],ax      ; reset count to delay
  823.  
  824.     call aniStepOnceFwd           ; do one step of the animation
  825.  
  826. @@return:
  827.     ret
  828. ENDP doDelayedAniStep
  829.  
  830.  
  831. ;------------------------------------------------------------
  832. ; myTickerInt
  833. ;
  834. ; My ticker interrupt, patching int 08h
  835. ;
  836. ; does the animating
  837. ;------------------------------------------------------------
  838. PROC myTickerInt NEAR
  839.     push bp
  840.     push ax bx cx dx si di ds es
  841.     sti
  842.  
  843.     ASSUME ds:NOTHING,ss:NOTHING
  844.  
  845.     cmp [aniOn],0
  846.     je @@return                 ; animation not on, return
  847.  
  848.     cmp [aniSpeedCount],0
  849.     je @@return                 ; if count==0 return
  850.     dec [aniSpeedCount]         ; else count--
  851.  
  852. @@return:
  853.     mov al,20h
  854.     out 20h,al      ; end of interrupt
  855.  
  856.     pushf
  857.     call [DWORD cs:startupTickerVec]    ; simulate old ticker int
  858.  
  859.     pop es ds di si dx cx bx ax
  860.     pop bp
  861.     iret
  862. ENDP myTickerInt
  863.  
  864.  
  865.  
  866. ;------------------------------------------------------------
  867. ; myMultiplexInt
  868. ;
  869. ; My multiplex interrupt, patching int 2fh
  870. ;
  871. ;
  872. ;------------------------------------------------------------
  873. PROC myMultiplexInt NEAR
  874. ASSUME ds:nothing
  875.     cmp ah,MultiplexCode
  876.     je @@askingthis
  877.     jmp [cs:startupMultiplexVec]    ; not this one, try next
  878.  
  879. @@askingthis:
  880.     or al,al
  881.     jne @@notfunc0
  882.  
  883.     ; requesting whether is installed
  884.     mov al,0FFh    ; indicate that dpAni is already installed
  885.     iret
  886.  
  887. @@notfunc0:
  888.     cmp al,MPRequestShutdown
  889.     jne @@notshutdown
  890.  
  891.     ; requesting shutdown
  892.  
  893.     ; reset sw ints
  894.     push dx
  895.     push ds        ; save regs
  896.  
  897.     ; restore orig MP interrupt intercept
  898.     lds dx,[DWORD cs:startupMultiplexVec]    ; ds:dx = original MP int
  899.     mov ax,252fh
  900.     int 21h
  901.  
  902.     ; restore orig Kb interrupt intercept
  903.     lds dx,[DWORD cs:startupKbVec]        ; ds:dx = original Kb int
  904.     mov ax,2516h
  905.     int 21h
  906.  
  907.     ; restore orig Ticker interrupt intercept
  908.     lds dx,[DWORD cs:startupTickerVec]      ; ds:dx = original Ticker int
  909.     mov ax,2508h
  910.     int 21h
  911.  
  912.     pop ds
  913.     pop dx        ; restore regs
  914.  
  915.     mov ax,cs    ; ax = para address of this TSR
  916.     iret
  917.  
  918. @@notshutdown:
  919.  
  920.     iret
  921. ENDP myMultiplexInt
  922.  
  923.  
  924. ;* transient portion ****************************************
  925.  
  926. StartTransient:
  927.  
  928. presentMessage:
  929.         db 'dpAni is already loaded - cannot install again',0ah,0dh
  930.         db 'Use "dpani /?" for help.',0ah,0dh,'$'
  931. successMessage:
  932.         db 'dpAni by Carl Chimes 1994 : successfully installed',0ah,0dh
  933. helpMessage:
  934.         db 'Keys in DeluxePaint IIE:',0ah,0dh
  935.         db '  [F12] to activate (only works once per DP session)',0ah,0dh
  936.         db '  [F11] pause/unpause animation',0ah,0dh
  937.         db '  [GREYENTER] [ALT+KPNUMBER] set first frame nr (starting from 1)',0ah,0dh
  938.         db '  [LEFTALT+GREYENTER] [ALT+KPNUMBER] set nr of frames',0ah,0dh
  939.         db '  [LEFTALT+GREYUP] increase speed',0ah,0dh
  940.         db '  [LEFTALT+GREYDOWN] decrease speed',0ah,0dh
  941.         db '  [LEFTALT+GREYLEFT] single step backwards',0ah,0dh
  942.         db '  [LEFTALT+GREYRIGHT] single step forwards',0ah,0dh
  943.         db '  [LEFTALT+W] [ALT+KPNUMBER] set frame width (default 16)',0ah,0dh
  944.         db '  [LEFTALT+H] [ALT+KPNUMBER] set frame height (default 16)',0ah,0dh
  945.         db '  [LEFTALT+M] toggle multiblock (tessellation) mode',0ah,0dh
  946.         db '  [LEFTALT+1] set Cycle animation type (default)',0ah,0dh
  947.         db '  [LEFTALT+2] set Ramp animation type',0ah,0dh
  948.         db 'Use "dpani" (from DOS) to install',0ah,0dh
  949.         db 'Use "dpani /U" (from DOS) to uninstall',0ah,0dh
  950.         db 'Use "dpani /?" (from DOS) for this help message',0ah,0dh,'$'
  951.  
  952. sucuninstallMessage:
  953.         db 'dpAni uninstalled',0ah,0dh,'$'
  954.  
  955. failuninstallMessage:
  956.         db 'dpAni not loaded - cannot uninstall',0ah,0dh,'$'
  957.  
  958.  
  959. installed    db 0    ; whether already installed (0FFh if is)
  960.  
  961. ;------------------------------------------------------------
  962. ; InitAndTerminate
  963. ;
  964. ; initialises program & terminates (and keeps resident portion
  965. ; resident).
  966. ;
  967. ;------------------------------------------------------------
  968. PROC InitAndTerminate NEAR
  969.     mov ah,30h
  970.     int 21h
  971.     cmp al,3
  972.     jge @@versionokay
  973.     int 20h        ; wrong dos version, exit
  974. @@versionokay:
  975.  
  976.     mov ax,MultiplexCode SHL 8
  977.     int 2Fh            ; al=0FFh -> already installed
  978.     mov [installed],al
  979.  
  980.     cmp [BYTE 80h],3
  981.     jne short @@nocommandline
  982.     cmp [WORD 82h],'u/'
  983.     je short @@deinstall
  984.     cmp [WORD 82h],'U/'
  985.     je short @@deinstall
  986.     cmp [WORD 82h],'?/'
  987.     je short @@help
  988.  
  989. @@nocommandline:
  990.     cmp [installed],0FFh
  991.     jne @@notinstalled    ; everything is okay - want to install
  992.  
  993.     ; already installed and not Uninstalling - print error & exit
  994.     mov dx,OFFSET presentMessage
  995.     mov ah,09h
  996.     int 21h        ; display presentMessage
  997.     mov ax,4c01h
  998.     int 21h        ; exit error status 1
  999.  
  1000. @@deinstall:
  1001.     cmp [installed],0FFh
  1002.     jne short @@cantuninstall
  1003.  
  1004.     ; already installed and want to Uninstall
  1005.     mov ax,(MultiplexCode SHL 8) OR MPRequestShutdown
  1006.     int 2Fh
  1007.     ; now ax has para address of TSR
  1008.     mov es,ax
  1009.     mov ah,49h
  1010.     int 21h            ; free mem block (of installed TSR)
  1011.     mov dx,OFFSET sucuninstallMessage
  1012.     mov ah,09h
  1013.     int 21h        ; display success uninstall message
  1014.     mov ax,4c00h
  1015.     int 21h     ; exit with status 0
  1016.  
  1017. @@cantuninstall:
  1018.     ; want to Uninstall but TSR not loaded
  1019.     mov dx,OFFSET failuninstallMessage
  1020.     mov ah,09h
  1021.     int 21h        ; display failed uninstall message
  1022.     mov ax,4c01h
  1023.     int 21h     ; exit with status 1
  1024.  
  1025. @@help:
  1026.     ; want to see help message
  1027.     mov dx,OFFSET helpMessage
  1028.     mov ah,09h
  1029.     int 21h     ; display help message
  1030.     mov ax,4c00h
  1031.     int 21h     ; exit with status 0
  1032.  
  1033. @@notinstalled:
  1034.  
  1035.     ; wish to install dpAni
  1036.  
  1037.     mov es,[2ch]
  1038.     mov ah,49h
  1039.     int 21h        ; free environment block
  1040.  
  1041.  
  1042.     ; initialise keybd int
  1043.     mov ax,3516h
  1044.     int 21h        ; es:bx= keybd int vector
  1045.     mov [WORD LOW startupKbVec],bx
  1046.     mov [WORD HIGH startupKbVec],es
  1047.     mov dx,OFFSET myKbInt
  1048.     mov ax,2516h
  1049.     int 21h        ; setup my keyboard interrupt intercept
  1050.  
  1051.  
  1052.     ; initialise multiplex int
  1053.     mov ax,352fh
  1054.     int 21h        ; es:bx= multiplex int vector
  1055.     mov [WORD LOW startupMultiplexVec],bx
  1056.     mov [WORD HIGH startupMultiplexVec],es
  1057.     mov dx,OFFSET myMultiplexInt
  1058.     mov ax,252fh
  1059.     int 21h        ; setup my keyboard interrupt intercept
  1060.  
  1061.     ; initialise ticker int
  1062.     mov ax,3508h
  1063.     int 21h     ; es:bx= ticker int vector
  1064.     mov [WORD LOW startupTickerVec],bx
  1065.     mov [WORD HIGH startupTickerVec],es
  1066.     mov dx,OFFSET myTickerInt
  1067.     mov ax,2508h
  1068.     int 21h     ; setup my ticker interrupt intercept
  1069.  
  1070.     mov dx,OFFSET successMessage
  1071.     mov ah,09h
  1072.     int 21h        ; display successMessage
  1073.  
  1074.     mov dx,OFFSET StartTransient + 15
  1075.     mov cl,4
  1076.     shr dx,cl
  1077.     mov ax,3100h    ; error status 0
  1078.     int 21h        ; terminate & stay resident (keep up to InitAndTerminate)
  1079. ENDP InitAndTerminate
  1080.  
  1081.  
  1082.  
  1083.  
  1084. END    ; of program
  1085.